const Cription = require('./static/Cription.js')
const Config = require('./config.js')
function showModal(content = '未开启设备蓝牙') {
  wx.showModal({
    content,
    title: '提示',
    showCancel: false,
    confirmText: '知道了',
  })
}
// 蓝牙数据传输报错场景
// 1. 信号变化，包括蓝牙关闭
// 2. 接收端异常，
class Ble extends Cription {
  constructor(cfg = Config) {
    super()
    cfg = {
      serviceId: "0000FF01-0000-1000-8000-00805F9B34FB",
      characteristicId: "0000FF02-0000-1000-8000-00805F9B34FB",
      characteristicIdSend: "0000FF03-0000-1000-8000-00805F9B34FB",
      connectTimeout: 10 * 1000,
      URL: 'https://oghafnxkic.execute-api.us-west-2.amazonaws.com/Prod/device/certificate/get',
      ...cfg,
    }
    this.cfg = cfg
    this.foundLock = false
    this.findDevices = {}
    this.tryConnectTimes = 10
    this.init()
  }
  async init() {
    wx.onBluetoothDeviceFound((res) => {
      if (this.foundHandle) {
        let reg
        if (typeof Config.BLE_NAME === 'string') {
          reg = new RegExp(Config.BLE_NAME, 'i')
        } else {
          reg = Config.BLE_NAME
        }
        let devices = res.devices.filter(x => reg.test(x.name || x.localName))
        devices.some(x => {
          this.findDevices[x.deviceId] = x
        })
        const foundDevices = Object.values(this.findDevices)
        console.log('target devices', foundDevices)
        let _foundDevices = foundDevices.map(x => ({ ...x, deviceMac: this.advertisDataToMac(x.advertisData) }))
        this.foundHandle && this.foundHandle(_foundDevices)
        return
      } else {
        console.log('found devices: ', res.devices)
        let devices = res.devices.filter(x => x.name || x.localName)
        if (devices.length > 0) {
          let reg = new RegExp(this.cfg.BLE_NAME, 'i')
          const device = devices.find(x => reg.test(x.name))
          if (device && device.deviceId && !this.foundLock) {
            this.foundLock = true
            this.cfg.deviceId = device.deviceId
            console.log('found device: ', device)
            this.connectDevice()
          }
        }
      }

    })
    try {
      // 当启动蓝牙开关后，反复调用此api，均会成功
      let res = await wx.openBluetoothAdapter()
      console.log('init BLE success:', res)
    } catch (e) {
      const { errCode, errMsg } = e
      if (errCode === 10001) {
        console.log('init BLE error: not open bluetooth', errMsg)
        showModal()
      }
    }
    try {
      wx.showNavigationBarLoading()
      await wx.startBluetoothDevicesDiscovery({ allowDuplicatesKey: true, interval: 800 })
    } catch (e) {
      console.log('start search error:', e)
    }
  }
  destory() {
    wx.closeBluetoothAdapter({
      complete: (msg) => {
        console.log('closeBluetoothAdapter msg', msg)
      }
    })
  }
  async connectDevice(deviceId) {
    if (!deviceId) {
      deviceId = this.cfg.deviceId
    }
    try {
      await wx.stopBluetoothDevicesDiscovery()
      const connect = await wx.createBLEConnection({
        deviceId,
        timeout: this.cfg.connectTimeout,
      })
      console.log('connect success: ', connect)
      const notify = await this.initNotify()
      this.created && this.created()
      wx.hideNavigationBarLoading()
      console.log('notify message: ', notify)
    } catch (e) {
      if (--this.tryConnectTimes > 0) {
        this.connectDevice(deviceId)
      }
      console.log('connect error: ', e)
    }
  }
  async initNotify(deviceId, serviceId, characteristicId) {
    if (!deviceId) {
      deviceId = this.cfg.deviceId
    }
    // IOS 兼容处理
    const { services } = await wx.getBLEDeviceServices({ deviceId })
    console.log('services: ', services)
    for (let service of services) {
      if (service.isPrimary) {
        const { characteristics } = await wx.getBLEDeviceCharacteristics({
          deviceId,
          serviceId: service.uuid,
        })
        console.log('characteristics: ', characteristics)
      }
    }
    try {
      let res = await wx.notifyBLECharacteristicValueChange({
        deviceId,
        serviceId: this.cfg.serviceId || serviceId,
        characteristicId: this.cfg.characteristicId || characteristicId,
        state: true,
      })
      console.log('using notify: ', res)
    } catch (e) {
      console.log('using notify error ', e)
    }
  }
  async writeValue(dataStr, deviceId, serviceId, characteristicIdSend) {
    if (!deviceId) {
      deviceId = this.cfg.deviceId
    }
    const pkgs = this.formatBleDataV2(dataStr, 'string')
    console.log(pkgs)
    this.doing && this.doing()
    for (let str of pkgs) {
      try {
        const buffer = this.hexToAb(str)
        let result = await wx.writeBLECharacteristicValue({
          deviceId,
          serviceId: serviceId || this.cfg.serviceId,
          characteristicId: characteristicIdSend || this.cfg.characteristicIdSend,
          value: buffer
        })
        console.log('write success: ', result)
      } catch (e) {
        console.log(e)
        this.writeValue(dataStr, deviceId, serviceId, characteristicIdSend)
      }
    }
  }
  notify(cb) {
    wx.onBLECharacteristicValueChange(async ({ value, ...params }) => {
      console.log(params)
      const res = this.notifyFormatV2(this.abToHex(value), 'string')
      if (res.type === 'resMsg') {
        this.destory()
        cb && cb(res.data)
      }
    })
  }
}
module.exports = Ble